package com.xspace.android.xafcommon.download;

import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
public class DownloadManager {
    public static final int UNKNOWN = -2; // Unknown task

    private int maxNumber = DownConstants.taskMaxNumber;

    private Vector<DownloadTask> mTasks = new Vector<DownloadManager.DownloadTask>(
            16);
    private HashMap<String, DownloadTask> mDoingTasks = new HashMap<String, DownloadManager.DownloadTask>(
            maxNumber);// Downloading task
    private HashMap<String, DownloadTask> mDoingImgTasks = new HashMap<String, DownloadManager.DownloadTask>(
            3);// Downloading Picture task
    private HashMap<String, DownloadTask> mPauseTasks = new HashMap<String, DownloadManager.DownloadTask>(); // suspend
    // task
    private DownloadObserver downloadObserver;
    private String URL_DOWNLOAD;

    public DownloadManager() {
        downloadObserver = new DownloadObserver();
        FileUtils.initDownloadTempDir();
    }


    public void addTask(String id, DownloadInfo downloads, String name,
                        boolean type, IDownloadListener downCallback) {
        if (!isExist(id)) {
            DownloadThread thread = new DownloadThread(id, downloads, this);
            thread.status = DownConstants.START;
            downloadObserver.addObserver(thread);
            mTasks.add(new DownloadTask(id, name, type, thread, downCallback));
            doTask();
        } else {
            setCallback(id, downCallback);
        }
    }

    private boolean isExist(String id) {
        boolean isExist = false;
        DownloadTask task = null;
        task = getTask(id, false);
        if (task != null) {
            isExist = true;
        } else {
            task = getDoingTask(id, false);
            if (task != null) {
                isExist = true;
            } else {
                task = getPauseTask(id, false);
                if (task != null) {
                    isExist = true;
                }
            }
        }
        return isExist;
    }

    private void addTask(DownloadTask task) {
        mTasks.add(task);
        doTask();
    }

    private void doTask() {
        if (!mTasks.isEmpty()) {
            DownloadManager.DownloadTask info;
            for (int j = 0; j < mTasks.size(); j++) {
                info = mTasks.get(j);
                if (!info.type && mDoingTasks.size() < maxNumber) {
                    int min = Math.min(mTasks.size(), maxNumber
                            - mDoingTasks.size());
                    DownloadTask task = null;
                    for (int i = 0; i < min; i++) {
                        info.downloadThread.downType = false;
                        task = mTasks.remove(0);
                        mDoingTasks.put(task.id, task);
                        task.downloadThread.resume();
                    }
                } else if (info.type && mDoingImgTasks.size() < 3) {
                    int min = Math
                            .min(mTasks.size(), 3 - mDoingImgTasks.size());
                    DownloadTask task = null;
                    for (int i = 0; i < min; i++) {
                        info.downloadThread.downType = true;
                        task = mTasks.remove(0);
                        mDoingImgTasks.put(task.id, task);
                        task.downloadThread.resume();
                    }
                }
            }
        }
    }

    public void pause(String id) {
        DownloadTask task = getTask(id, true);
        if (task != null) {
            mPauseTasks.put(task.id, task);
        } else {
            task = getDoingTask(id, true);
            if (task != null) {
                task.downloadThread.pause();
                mPauseTasks.put(task.id, task);
            }
        }
    }

    public int getStatus(String id) {
        DownloadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getStatus();
        }
    }

    public float getProgress(String id) {
        DownloadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getProgress();
        }
    }

    public long getDowned(String id) {
        DownloadTask task = getTask(id, false);
        if (task == null)
            task = getDoingTask(id, false);
        if (task == null)
            task = getPauseTask(id, false);
        if (task == null) {
            return UNKNOWN;
        } else {
            return task.downloadThread.getDownloaded();
        }
    }

    public void cancel(String id) {
        DownloadTask task = getTask(id, true);
        if (task == null) {
            task = getPauseTask(id, true);
            if (task == null) {
                task = getDoingTask(id, false);
                task.downloadThread.cancel();
            }
        }
        if (task != null && task.listener != null) {
                task.listener.onCancelDown(null, -1);
        }

    }

    public void resume(String id) {
        DownloadTask task = getPauseTask(id, true);
        if (task != null) {
            addTask(task);
        }
    }


    public synchronized void setCallback(String id, IDownloadListener callback) {
        DownloadTask task = getTask(id, false);
        if (task != null) {
            task.listener = callback;
        } else {
            task = getDoingTask(id, false);
            if (task != null) {
                task.listener = callback;
            } else {
                task = getPauseTask(id, false);
                if (task != null) {
                    task.listener = callback;
                }
            }
        }
    }

    private DownloadTask getTask(String id, boolean isRemove) {
        int index = mTasks.indexOf(new DownloadTask(id));
        if (index != -1) {
            if (!isRemove) {
                return mTasks.get(index);
            } else {
                return mTasks.remove(index);
            }
        }

        return null;
    }

    private DownloadTask getDoingImgTask(String id, boolean isRemove) {
        DownloadTask task = mDoingImgTasks.get(id);
        if (task != null) {
            if (isRemove) {
                mDoingImgTasks.remove(id);
            }
            return task;
        }
        return null;
    }

    private DownloadTask getDoingTask(String id, boolean isRemove) {
        DownloadTask task = mDoingTasks.get(id);
        if (task != null) {
            if (isRemove) {
                mDoingTasks.remove(id);
            }
            return task;
        }
        return null;
    }

    private DownloadTask getPauseTask(String id, boolean isRemove) {
        DownloadTask task = mPauseTasks.get(id);
        if (task != null) {
            if (isRemove) {
                mPauseTasks.remove(id);
            }
            return task;
        }
        return null;
    }

    public synchronized IDownloadListener getCallback(String id) {
        DownloadTask task = getTask(id, false);
        if (task != null)
            return task.listener;
        else {
            task = getDoingTask(id, false);
            if (task != null) {
                return task.listener;
            } else {
                task = getPauseTask(id, false);
                if (task != null) {
                    return task.listener;
                }
            }
        }
        return null;
    }

    public void setURL_DOWNLOAD(String uRL_DOWNLOAD) {
        URL_DOWNLOAD = uRL_DOWNLOAD;
    }

    public String getURL_DOWNLOAD() {
        return URL_DOWNLOAD;
    }

    class DownloadObserver implements Observer {
        int i = 0;

        public void addObserver(DownloadThread download) {
            download.addObserver(this);
        }

        @Override
        public void update(Observable observable, Object data) {
            DownloadThread download = (DownloadThread) observable;
            DownloadTask task = null;
            switch (download.getStatus()) {
                case DownConstants.CANCELLED: // cancel status
                    if (!download.downType) {
                        task = getDoingTask(download.getId(), true);
                        if (task == null) {
                            task = getPauseTask(download.getId(), true);
                        }
                        if (task != null) {
                            i = 0;
                            if (task.listener != null) {
                                task.listener.onCancelDown(download
                                        .getDownloads(), download
                                        .getCurrentNumber());
                                doTask();
                            }
                        }
                    }
                    break;
                case DownConstants.DOWNLOADING: // downloading status
                    if (!download.downType) {
                        task = getDoingTask(download.getId(), false);
                        if (task != null) {
                            if (task.listener != null) {
                                task.listener.onDowning(download
                                                .getDownloaded(), download.getSize(),
                                        download.getProgress(),
                                        download.getSpeed(), download
                                                .getDownloads(), download
                                                .getCurrentNumber());
                            }
                        }
                    }
                    break;
                case DownConstants.ERROR: // download error status
                    if (download.downType) {
                        task = getDoingImgTask(download.getId(), true);
                        if (task != null) {
                        }
                    } else {
                        task = getDoingTask(download.getId(), true);
                        if (task != null) {
                            i = 0;
                            if (download.getProgress() > 0)
                                mPauseTasks.put(task.id, task);// push suspend task
                            if (task.listener != null) {
                                task.listener.onDownError(download
                                                .getDownloaded(), download
                                                .getProgress(),
                                        download.getDownloads(), download
                                                .getCurrentNumber());
                            }
                        }
                    }
                    break;
                case DownConstants.PAUSED: // suspend status
                    if (!download.downType) {
                        task = getDoingTask(download.getId(), false);
                        if (task == null) {
                            task = getPauseTask(download.getId(), false);
                        }
                        if (task != null) {
                            if (task.listener != null) {
                                task.listener.onPauseDown(download
                                        .getDownloads(), download
                                        .getCurrentNumber());
                                doTask();
                            }
                        }
                    }
                    break;
                case DownConstants.COMPLETE: // finish status
                    if (download.downType) {
                        task = getDoingImgTask(download.getId(), true);
                        if (task != null) {
                            DownloadInfo info = download.getDownloads();
                        }
                    } else {
                        task = getDoingTask(download.getId(), true);
                        boolean checkFlag = false;
                        if (task != null) {
                            i = 0;
                            DownloadInfo info = download.getDownloads();
                            try {
                                FileUtils.deleteFile(info.saveFileName);
                                if (null == info.req.md5 || info.req.md5.equals("")) {
                                    FileUtils.reName(info.tmpFileName,
                                            info.saveFileName);
                                    checkFlag = true;
                                } else if (info.req.md5.equals(FileMD5Check
                                        .getHash(info.tmpFileName))) {// 通过md5验证文件的完整性
                                    FileUtils.reName(info.tmpFileName,
                                            info.saveFileName);
                                    checkFlag = true;
                                } else {
                                    FileUtils.deleteFile(info.tmpFileName);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            if (task.listener != null) {
                                task.listener.onDownAllFinished(info, checkFlag);
                                try {
                                    Thread.sleep(500);
                                    doTask();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }

                            }
                        }
                    }
                    break;
            }
        }
    }

    /**
     * @version V1.0.0
     * @ClassName: DownloadTask
     * @author:qbluo
     * @Date：2012-8-22
     * @Description: downLoad Task 实体类
     */
    public static class DownloadTask {
        public String id;
        public DownloadThread downloadThread;
//        public IDownCallback downCallback;
        public IDownloadListener listener;
        public String name;
        public String loadPath;
        public boolean type = false;

        public DownloadTask(String id) {
            this.id = id;
        }

//        public DownloadTask(String id, String name, boolean type,
//                            DownloadThread downloadThread, IDownCallback downCallback) {
//            this.id = id;
//            this.name = name;
//            this.type = type;
//            this.downloadThread = downloadThread;
//            this.downCallback = downCallback;
//        }


        public DownloadTask(String id, String name, boolean type,
                            DownloadThread downloadThread, IDownloadListener downCallback) {
            this.id = id;
            this.name = name;
            this.type = type;
            this.downloadThread = downloadThread;
            this.listener = downCallback;
        }

        @Override
        public boolean equals(Object o) {
            if (id.equals(((DownloadTask) o).id)) {
                return true;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return id.hashCode();
        }
    }
}
